/*******************************************************************************
 * Copyright (c) 2022 - 2025 NVIDIA Corporation & Affiliates.                  *
 * All rights reserved.                                                        *
 *                                                                             *
 * This source code and the accompanying materials are made available under    *
 * the terms of the Apache License 2.0 which accompanies this distribution.    *
 ******************************************************************************/

// clang-format off
// RUN: cudaq-quake  %s | cudaq-opt --unrolling-pipeline | cudaq-translate --convert-to=openqasm2 | FileCheck %s
// clang-format on

#include <cudaq.h>
#include <fstream>

struct crystal_5_kernel {
  // Crystal_5 QPU.
  //       QB1
  //        |
  // QB2 - QB3 - QB4
  //        |
  //       QB5

  void operator()() __qpu__ {
    cudaq::qvector q(5);
    x(q[0]);

    for (int i = 0; i < 4; i++) {
      x<cudaq::ctrl>(q[i], q[i + 1]);
    }
    x<cudaq::ctrl>(q[0], q[2], q[1]);
    auto result = mz(q);
  }
};

int main() {
  auto counts = cudaq::sample(crystal_5_kernel{});
  counts.dump();
}

// CHECK:   // Code generated by NVIDIA's nvq++ compiler
// CHECK:   OPENQASM 2.0;

// CHECK:   include "qelib1.inc";

// CHECK:   gate ZN16crystal_5_kernelclEv(param0)  {
// CHECK:   }

// CHECK:   qreg var0[5];
// CHECK:   x var0[0];
// CHECK:   cx var0[0], var0[1];
// CHECK:   cx var0[1], var0[2];
// CHECK:   cx var0[2], var0[3];
// CHECK:   cx var0[3], var0[4];
// CHECK:   ccx var0[0], var0[2], var0[1];
// CHECK:   creg var6[5];
// CHECK:   measure var0 -> var6;
